package com.nnnu.wsnackshop.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nnnu.wsnackshop.constant.MessageConstants;
import com.nnnu.wsnackshop.constant.StatusCodeConstants;
import com.nnnu.wsnackshop.controller.base.BaseController;
import com.nnnu.wsnackshop.exception.BaseException;
import com.nnnu.wsnackshop.mapper.MembersMapper;
import com.nnnu.wsnackshop.mapper.UsersMapper;
import com.nnnu.wsnackshop.pojo.dto.LoginDTO;
import com.nnnu.wsnackshop.pojo.dto.PhoneLoginDTO;
import com.nnnu.wsnackshop.pojo.dto.SendSmsCodeDTO;
import com.nnnu.wsnackshop.pojo.dto.WechatLoginDTO;
import com.nnnu.wsnackshop.pojo.dto.WechatPhoneLoginDTO;
import com.nnnu.wsnackshop.pojo.entity.Members;
import com.nnnu.wsnackshop.pojo.entity.Users;
import com.nnnu.wsnackshop.pojo.vo.CouponVO;
import com.nnnu.wsnackshop.pojo.vo.WechatLoginVO;
import com.nnnu.wsnackshop.result.Result;
import com.nnnu.wsnackshop.service.AuthService;
import com.nnnu.wsnackshop.service.IUserCouponsService;
import com.nnnu.wsnackshop.utils.JwtUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 认证 控制器
 * </p>
 */
@RestController
@RequestMapping("/api/auth")
@Tag(name = "认证接口", description = "包含登录、注册、重置密码等功能")
@Slf4j
@RequiredArgsConstructor
public class AuthController extends BaseController {
    private final AuthService authService;
    private final UsersMapper usersMapper;
    private final MembersMapper membersMapper;
    private final IUserCouponsService userCouponsService;

    @Operation(summary = "用户登录")
    @PostMapping("/login")
    public Result<?> login(@RequestBody LoginDTO loginDTO) {
        log.info("用户登录: {}", loginDTO.getUsername());
        return Result.success(authService.login(loginDTO), MessageConstants.LOGIN_SUCCESS);
    }

    @Operation(summary = "微信小程序登录")
    @PostMapping("/wechat/login")
    public Result<WechatLoginVO> wechatLogin(@RequestBody WechatLoginDTO wechatLoginDTO) {
        log.info("微信小程序登录请求开始");
        try {
            WechatLoginVO loginResult = authService.wechatLogin(wechatLoginDTO);
            log.info("微信小程序登录成功，用户ID: {}, 登录已响应", loginResult.getUserInfo().getUserId());
            return Result.success(loginResult, "登录成功");
        } catch (Exception e) {
            log.error("微信小程序登录异常: {}", e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "登录失败：" + e.getMessage());
        } finally {
            log.info("微信小程序登录请求结束");
        }
    }

    @Operation(summary = "微信手机号登录")
    @PostMapping("/wechat/phone-login")
    public Result<WechatLoginVO> wechatPhoneLogin(@RequestBody WechatPhoneLoginDTO wechatPhoneLoginDTO) {
        log.info("微信手机号登录请求");
        try {
            WechatLoginVO loginResult = authService.wechatPhoneLogin(wechatPhoneLoginDTO);
            log.info("微信手机号登录成功，用户ID: {}", loginResult.getUserInfo().getUserId());
            return Result.success(loginResult, "登录成功");
        } catch (Exception e) {
            log.error("微信手机号登录异常: {}", e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "登录失败：" + e.getMessage());
        }
    }

    @Operation(summary = "发送手机验证码")
    @PostMapping("/send-sms-code")
    public Result<Boolean> sendSmsCode(@Valid @RequestBody SendSmsCodeDTO sendSmsCodeDTO) {
        log.info("发送手机验证码请求，手机号: {}", sendSmsCodeDTO.getPhone());
        try {
            boolean result = authService.sendSmsCode(sendSmsCodeDTO);
            return Result.success(result, "验证码发送成功");
        } catch (Exception e) {
            log.error("发送验证码异常: {}", e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @PostMapping("/phone-login")
    @Operation(summary = "手机号验证码登录")
    public Result<WechatLoginVO> phoneLogin(@RequestBody @Valid PhoneLoginDTO phoneLoginDTO) {
        try {
            log.info("手机号登录请求: {}", phoneLoginDTO.getPhone());
            WechatLoginVO loginResult = authService.phoneLogin(phoneLoginDTO);
            return Result.success(loginResult);
        } catch (UnexpectedRollbackException e) {
            // 捕获事务回滚异常，这通常是由于发券超时导致的
            log.error("手机号登录事务回滚异常: {}", e.getMessage(), e);
            // 尝试重新获取用户信息，确保用户能够登录
            try {
                Users user = usersMapper.selectOne(
                        new LambdaQueryWrapper<Users>().eq(Users::getPhone, phoneLoginDTO.getPhone()));
                if (user != null) {
                    Members member = membersMapper.selectOne(
                            new LambdaQueryWrapper<Members>().eq(Members::getUserId, user.getId()));
                    if (member != null) {
                        String token = JwtUtil.createTokenWithUser(user);
                        WechatLoginVO loginVO = WechatLoginVO.builder()
                                .token(token)
                                .userInfo(member)
                                .newUserCoupons(new ArrayList<>())
                                .build();
                        log.info("手机号登录事务回滚后重新构建登录信息成功");
                        return Result.success(loginVO);
                    }
                }
            } catch (Exception ex) {
                log.error("重新构建登录信息失败: {}", ex.getMessage(), ex);
            }
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "登录过程中发生错误，请稍后重试");
        } catch (Exception e) {
            log.error("手机号登录异常: {}", e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @Operation(summary = "领取新人优惠券")
    @GetMapping("/claim-new-user-coupons")
    public Result<?> claimNewUserCoupons() {
        if (!isLogin()) {
            return Result.error(StatusCodeConstants.UNAUTHORIZED, MessageConstants.NOT_LOGIN);
        }

        Integer userId = getUserId();
        log.info("用户{}领取新人优惠券", userId);

        try {
            List<CouponVO> coupons = userCouponsService.issueNewUserCoupons(userId);
            return Result.success(coupons, "领取成功");
        } catch (BaseException e) {
            log.warn("用户{}领取新人优惠券失败: {}", userId, e.getMessage());
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, e.getMessage());
        } catch (Exception e) {
            log.error("用户{}领取新人优惠券异常: {}", userId, e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "系统繁忙，请稍后再试");
        }
    }

    @Operation(summary = "刷新token")
    @PostMapping("/refresh")
    public Result<?> refreshToken() {
        log.info("开始刷新token");
        String oldToken = (String) SecurityUtils.getSubject().getPrincipal();
        if (oldToken == null) {
            log.warn("刷新token失败：未获取到当前token");
            return Result.error(StatusCodeConstants.UNAUTHORIZED, "未登录或登录已过期");
        }

        String newToken = authService.refreshToken(oldToken);
        if (newToken != null) {
            log.info("token刷新成功");
            return Result.success(newToken, "token刷新成功");
        } else {
            log.warn("token刷新失败");
            return Result.error(StatusCodeConstants.UNAUTHORIZED, "token刷新失败，请重新登录");
        }
    }

    @Operation(summary = "用户退出登录")
    @PostMapping("/logout")
    public Result<?> logout() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            log.info("用户退出登录: {}", subject.getPrincipal());
            subject.logout();
            return Result.success(MessageConstants.LOGOUT_SUCCESS);
        }
        return Result.success(MessageConstants.NOT_LOGIN);
    }

    @PostMapping("/wechat/get-openid")
    @Operation(summary = "获取微信openid但不登录")
    public Result<Map<String, String>> getWechatOpenid(@RequestBody @Valid WechatLoginDTO wechatLoginDTO) {
        try {
            log.info("获取微信openid请求，code: {}", wechatLoginDTO.getCode());
            String openid = authService.getWechatOpenid(wechatLoginDTO.getCode());

            if (openid != null && !openid.isEmpty()) {
                Map<String, String> result = new HashMap<>();
                result.put("openid", openid);
                return Result.success(result);
            } else {
                return Result.error(StatusCodeConstants.BAD_REQUEST, "获取openid失败");
            }
        } catch (Exception e) {
            log.error("获取微信openid异常: {}", e.getMessage(), e);
            return Result.error(StatusCodeConstants.INTERNAL_SERVER_ERROR, "获取openid失败: " + e.getMessage());
        }
    }
}
